/**
 * 身体項目定数（質問入力画面）
 */
export const BodyItemConstant = Object.freeze({
  // 年齢【歳】
  AGE: _makeConstantValue('age', '年齢', _range(40, 74).map(i => [ i, `yearsOld${i}`, `${i}歳` ]), false),

  // 性別
  GENDER: _makeConstantValue('gender', '性別', [
    [ 1, 'male', '男性' ],
    [ 2, 'female', '女性' ],
  ]),

  // 身長【cm】
  BODY_HEIGHT: _makeConstantValue('bodyHeight', '身長', _range(120, 220).map(i => [ i, `height${i}`, `${i}cm` ]), false),

  // 体重【kg】
  BODY_WEIGHT: _makeConstantValue('bodyWeight', '体重', _range(30, 299).map(i => [ i, `weight${i}`, `${i}kg` ]), false),

  // 喫煙習慣
  SMOKING_HABIT: _makeConstantValue('smokingHabit', '喫煙習慣', [
    [ 1, 'isSmoking', '吸っている' ],
    [ 2, 'stoppedShortAgo', 'やめた(禁煙期間20年未満)' ],
    [ 3, 'stoppedLongAgo', 'やめた(禁煙期間20年以上)' ],
    [ 4, 'noSmoking', '吸わない' ],
  ]),

  // 飲酒習慣
  ALCOHOL_HABIT: _makeConstantValue('alcoholHabit', '飲酒習慣', [
    [ 1, 'isDrinking', '飲む' ],
    [ 2, 'noDrinking', '飲まない' ],
    [ 3, 'stopped', 'やめた' ],
  ]),

  // 飲酒頻度
  ALCOHOL_FREQUENCY: _makeConstantValue('alcoholFrequency', '飲酒頻度', [
    [ 1, 'monthLess1', '月1日未満' ],
    [ 2, 'monthLess3', '月1～3日' ],
    [ 3, 'weekLess2', '週1～2日' ],
    [ 4, 'weekLess4', '週3～4日' ],
    [ 5, 'almostEveryDay', '週5～6日' ],
    [ 6, 'everyDay', '毎日' ],
  ]),

  // 飲酒量（日本酒）
  ALCOHOL_AMOUNT_SAKE: _makeConstantValue('alcoholAmountSake', '日本酒', [
    [ 1, 'noDrinking', '飲まない' ],
    [ 2, 'almostNot', '0.5合未満' ],
    [ 3, 'less1', '0.5～1合未満' ],
    [ 4, 'equal1', '1合' ],
    [ 5, 'equal2', '2合' ],
    [ 6, 'equal3', '3合' ],
    [ 7, 'equal4', '4合' ],
    [ 8, 'less6', '5～6合' ],
    [ 9, 'more7', '7合以上' ],
  ]),

  // 飲酒量（焼酎または泡盛）
  ALCOHOL_AMOUNT_SHOCHU: _makeConstantValue('alcoholAmountShochu', '焼酎または泡盛', [
    [ 1, 'noDrinking', '飲まない' ],
    [ 2, 'almostNot', '0.5合未満' ],
    [ 3, 'less1', '0.5～1合未満' ],
    [ 4, 'equal1', '1合' ],
    [ 5, 'equal2', '2合' ],
    [ 6, 'equal3', '3合' ],
    [ 7, 'equal4', '4合' ],
    [ 8, 'less6', '5～6合' ],
    [ 9, 'more7', '7合以上' ],
  ]),

  // 飲酒量（ビールまたは発泡酒）
  ALCOHOL_AMOUNT_BEER: _makeConstantValue('alcoholAmountBeer', 'ビールまたは発泡酒', [
    [ 1, 'noDrinking', '飲まない' ],
    [ 2, 'almostNot', '0.5本未満' ],
    [ 3, 'less1', '0.5～1本未満' ],
    [ 4, 'equal1', '1本' ],
    [ 5, 'equal2', '2本' ],
    [ 6, 'equal3', '3本' ],
    [ 7, 'equal4', '4本' ],
    [ 8, 'less6', '5～6本' ],
    [ 9, 'more7', '7本以上' ],
  ]),

  // 飲酒量（威士忌或白兰地）
  ALCOHOL_AMOUNT_WHISKEY: _makeConstantValue('alcoholAmountWhiskey', 'ウィスキーまたはブランデー', [
    [ 1, 'noDrinking', '不喝' ],
    [ 2, 'almostNot', '不到半杯' ],
    [ 3, 'less1', '0.5～1杯' ],
    [ 4, 'equal1', '1杯' ],
    [ 5, 'equal2', '2杯' ],
    [ 6, 'equal3', '3杯' ],
    [ 7, 'equal4', '4杯' ],
    [ 8, 'less6', '5～6杯' ],
    [ 9, 'more7', '7杯以上' ],
  ]),

  // 飲酒量（葡萄酒）
  ALCOHOL_AMOUNT_WINE: _makeConstantValue('alcoholAmountWine', 'ワイン', [
    [ 1, 'noDrinking', '不喝' ],
    [ 2, 'almostNot', '不到半杯' ],
    [ 3, 'less1', '0.5～1杯' ],
    [ 4, 'equal1', '1杯' ],
    [ 5, 'equal2', '2杯' ],
    [ 6, 'equal3', '3杯' ],
    [ 7, 'equal4', '4杯' ],
    [ 8, 'less6', '5～6杯' ],
    [ 9, 'more7', '7杯以上' ],
  ]),

  // 運動習慣（座っている時間）
  EXERCISE_TIME_SITTING: _makeConstantValue('exerciseTimeSitting', '座っている時間', [
    [ 1, 'short', '不到3小时' ],
    [ 2, 'middle', '3～8小时' ],
    [ 3, 'long', '8小时以上' ],
  ]),

  // 運動習慣（立ったり歩いたりしている時間）
  EXERCISE_TIME_STANDING: _makeConstantValue('exerciseTimeStanding', '立ったり歩いたりしている時間', [
    [ 1, 'short', '不到1小时' ],
    [ 2, 'middle', '1～3小时' ],
    [ 3, 'long', '3小时以上' ],
  ]),

  // 運動習慣（肉体労働やスポーツをする時間）
  EXERCISE_TIME_LABORING: _makeConstantValue('exerciseTimeLaboring', '肉体労働やスポーツをする時間', [
    [ 1, 'none', '没有' ],
    [ 2, 'short', '不到1小时' ],
    [ 3, 'long', '1小时以上' ],
  ]),

  // 塩蔵品（塩辛、たらこ、すじこ）
  SALINE_FOOD: _makeConstantValue('salineFood', '塩蔵品', [
    [ 1, 'none', '完全不吃' ],
    [ 2, 'sometimes', '偶尔吃' ],
    [ 3, 'weekLess2', '一周1～2日' ],
    [ 4, 'weekLess4', '一周3～4日' ],
    [ 5, 'almostEveryDay', '几乎每天' ],
  ]),

  // 糖尿病の治療
  DIABETES_CURE_FLG: _makeConstantValue('diabetesCureFlg', '糖尿病', [
    [ 1, 'yes', '是的' ],
    [ 0, 'no', '不是' ],
  ]),

  // 血糖値（空腹時）【mg/dl】
  BLOOD_SUGAR_LEVEL_FASTING: _makeConstantValue('bloodSugarLevelFasting', '空腹時', [
    [ 1, 'low', '99mg/dl以下' ],
    [ 2, 'middle', '100mg/dl～125mg/dl' ],
    [ 3, 'high', '126mg/dl以上' ],
  ]),

  // 血糖値（随時）【mg/dl】
  BLOOD_SUGAR_LEVEL_ANYTIME: _makeConstantValue('bloodSugarLevelAnytime', '随時', [
    [ 1, 'low', '139mg/dl以下' ],
    [ 2, 'middle', '140mg/dl～199mg/dl' ],
    [ 3, 'high', '200mg/dl以上' ],
  ]),

  // 降圧剤
  ANTIHYPERTENSIVE_FLG: _makeConstantValue('antihypertensiveFlg', '降圧剤', [
    [ 1, 'yes', '是的' ],
    [ 0, 'no', '不是' ],
  ]),

  // 最高（収縮期）血圧【mmHg】
  MAX_BLOOD_PRESSURE: _makeConstantValue('maxBloodPressure', '最高血圧（収縮期）', _range(70, 210).map(i => [ i, `bloodMax${i}`, `${i}mmHg` ]), false),

  // 最低（拡張期）血圧【mmHg】
  MIN_BLOOD_PRESSURE: _makeConstantValue('minBloodPressure', '最低血圧（拡張期）', _range(30, 130).map(i => [ i, `bloodMin${i}`, `${i}mmHg` ]), false),

  // HDLコレステロール【mg/dl】
  HDL_CHOLESTEROL: _makeConstantValue('hdlCholesterol', 'HDLコレステロール', _range(5, 170).map(i => [ i, `hdl${i}`, `${i}mg/dl` ]), false),

  // LDLコレステロール【mg/dl】
  LDL_CHOLESTEROL: _makeConstantValue('ldlCholesterol', 'LDLコレステロール', _range(10, 330).map(i => [ i, `ldl${i}`, `${i}mg/dl` ]), false),

  // 中性脂肪（トリグゼライド）【mg/dl】
  TRIGLYCERIDE: _makeConstantValue('triglyceride', '中性脂肪', _range(10, 400).map(i => [ i, `trigly${i}`, `${i}mg/dl` ]), false),

  // 家族の既往歴（胃がん）
  FAMILY_ANAMNESIS_FLG: _makeConstantValue('familyAnamnesisFlg', '家族の既往歴', [
    [ 1, 'yes', '是的' ],
    [ 0, 'no', '不是' ],
  ]),

  // 抗体検査（ヘリコバクター・ピロリ菌）
  HELICOBACTER_PYLORI_FLG: _makeConstantValue('helicobacterPyloriFlg', '抗体検査', [
    [ 1, 'yes', '是的(陽性)' ],
    [ 0, 'no', '不是(陰性)' ],
  ]),

  // 慢性胃炎
  CHRONIC_GASTRITIS_FLG: _makeConstantValue('chronicGastritisFlg', '慢性胃炎', [
    [ 1, 'yes', '是的' ],
    [ 0, 'no', '不是' ],
  ]),

});

/**
 * シミュレーション項目定数（リスク軽減シミュレーション画面）
 */
export const SimulationItemConstant = Object.freeze(Object.assign({}, BodyItemConstant, {

  // 喫煙習慣
  SMOKING_HABIT: _makeConstantValue('smokingHabit', '喫煙', [
    [ 1, 'isSmoking', '吸着' ],
    [ 4, 'noSmoking', '不吸' ],
  ]),

  // 糖尿病の治療
  DIABETES_CURE_FLG: _makeConstantValue('diabetesCureFlg', '糖尿病', [
    [ 1, 'yes', '正在治疗' ], // 治疗していない
    [ 0, 'no', '没有治疗' ], // 治疗していない
  ]),

  // 降圧剤
  ANTIHYPERTENSIVE_FLG: _makeConstantValue('antihypertensiveFlg', '降圧剤', [
    [ 1, 'yes', '正在服用' ],// 服用している
    [ 0, 'no', '没有服用' ], // 服用していない
  ]),

  // 最高（収縮期）血圧【mmHg】
  MAX_BLOOD_PRESSURE: _makeConstantValue('maxBloodPressure', '最高血圧', _range(70, 210).map(i => [ i, `bloodMax${i}`, `${i}mmHg` ]), false),

  // 最低（拡張期）血圧【mmHg】
  MIN_BLOOD_PRESSURE: _makeConstantValue('minBloodPressure', '最低血圧', _range(30, 130).map(i => [ i, `bloodMin${i}`, `${i}mmHg` ]), false),

  // HDLコレステロール【mg/dl】
  HDL_CHOLESTEROL: _makeConstantValue('hdlCholesterol', 'HDLコレステロール', _range(5, 170).map(i => [ i, `hdl${i}`, `${i}mg/dl` ]), false),

  // LDLコレステロール【mg/dl】
  LDL_CHOLESTEROL: _makeConstantValue('ldlCholesterol', 'LDLコレステロール', _range(10, 330).map(i => [ i, `ldl${i}`, `${i}mg/dl` ]), false),

  // 中性脂肪（トリグゼライド）【mg/dl】
  TRIGLYCERIDE: _makeConstantValue('triglyceride', '中性脂肪', _range(10, 400).map(i => [ i, `trigly${i}`, `${i}mg/dl` ]), false),

}));

/**
 * 定数値不変オブジェクト生成ヘルパー関数です。
 * 以下のようなオブジェクトを生成します。
 *
 *   {
 *     id: 'gender',
 *     label: '性別',
 *     choices: [
 *       MALE,
 *       FEMALE,
 *     ],
 *     MALE: {
 *       id: 'male',
 *       label: '男性',
 *       value: 1,
 *     },
 *     FEMALE: {
 *       id: 'female',
 *       label: '女性',
 *       value: 2,
 *     },
 *   }
 *
 * @param {string} id 識別子（キャメルケース）
 * @param {string} label 名称
 * @param {Array.<Array>=} groups 選択肢グループ（[選択値(数値), 識別子, 選択名称]）の配列（2次元配列）
 * @param {boolean=} bypass 選択肢のプロパティアクセスをしない場合、false（省略した場合、true）
 * @return {Object} 定数値オブジェクト
 */
function _makeConstantValue(id, label, groups = [], bypass = true) {
  return __bypass_value__(bypass, Object.create({
    toString: function() {
      return this.id;
    },
    getValues: function() {
      return this.choices.map(choice => choice.value);
    },
    getLabels: function() {
      return this.choices.map(choice => choice.label);
    },
    getLabel: function(value) {
      return (this.choices.find(choice => choice.value == value) || {}).label;  // eslint-disable-line eqeqeq
    },
  }, {
    id: {
      value: id,
      enumerable: true,
    },
    label: {
      value: label,
      enumerable: true,
    },
    choices: {
      value: __value_label__(groups),
      enumerable: true,
    },
  }));

  function __value_label__(groups = []) { // eslint-disable-line no-shadow
    return Object.freeze(groups.map(group => (Object.freeze(Object.create({
      toString: function() {
        return String(this.value);
      },
    }, {
      value: {
        value: group[0],
        enumerable: true,
      },
      id: {
        value: group[1],
        enumerable: true,
      },
      label: {
        value: group[2],
        enumerable: true,
      },
    })))));
  }

  function __bypass_value__(enable, obj) {
    if (enable) {
      obj.choices.forEach(choice => {
        // キャメルケース → スネークケース（大文字）
        obj[choice.id.replace(/(.)([A-Z])/g, '$1_$2').toUpperCase()] = choice;
      });
    }
    return Object.freeze(obj);
  }
}

/**
 * 指定した範囲の配列を返すヘルパー関数です（境界値を含む）。
 * @param {number} start 開始値
 * @param {number=} stop 終了値（省略した場合、0からstartまでの配列）
 * @param {number=} step ステップ数（省略した場合、1）
 * @return {Array.<number>} startからstopまでの数値配列
 */
function _range(start, stop, step = 1) {
  if (arguments.length <= 1) {
    stop = start || 0;
    start = 0;
  }

  let length = Math.max(Math.ceil((stop - start + 1) / step), 0);
  let range = Array(length);

  for (let idx = 0; idx < length; ++idx, start += step) {
    range[idx] = start;
  }

  return range;
}
